package com.carcenter.order.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.carcenter.common.constant.appointment.AppointmentConstant;
import com.carcenter.common.exception.Assert;
import com.carcenter.common.exception.BusinessException;
import com.carcenter.common.result.Result;
import com.carcenter.common.result.enums.impl.BusinessCode;
import com.carcenter.common.result.enums.impl.ResultCode;
import com.carcenter.order.entity.*;
import com.store.client.StoreApi;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
public class AppointmentTrasationalService {
    @Autowired
    IAppointmentMasterService appointmentMasterService;

    @Autowired
    private IAppointmentProcessService appointmentProcessService;

    @Autowired
    private StoreApi storeApi;

    @Autowired
    IProductsService productsService;
    @Autowired
    IServicesService servicesService;

    @Autowired
    RedisTemplate redisTemplate;



    @Autowired
    private IAppointmentDetailService appointmentDetailService;

    // 注入自定义线程池（名称与@Bean("appointmentExecutor")一致）
    @Autowired
    @Qualifier("appointmentExecutor") // 必须指定Bean名称，避免歧义
    private Executor appointmentExecutor;

    public long countUserAppointmentsToday(Integer userId) {
        LocalDate today = LocalDate.now();
        LocalDateTime startTime = today.atStartOfDay();
        LocalDateTime endTime = today.plusDays(1).atStartOfDay();

        return appointmentMasterService.count(new LambdaQueryWrapper<AppointmentMaster>()
                .eq(AppointmentMaster::getUserId, userId)
                .ge(AppointmentMaster::getCreateTime, startTime)
                .lt(AppointmentMaster::getCreateTime, endTime));
    }

    //添加缓存重建锁：在 getStationCount 中使用 Redis 的 setIfAbsent 实现分布式锁，确保同一时间只有一个线程重建缓存。
    public Integer getStationCount(Integer storeId) {
        String cacheKey = "appointment:station_count:" + storeId;
        Integer stationCount = (Integer) redisTemplate.opsForValue().get(cacheKey);
        if (stationCount != null) {
            return stationCount;
        }
        // 缓存重建锁（10秒过期，避免死锁）
        String lockKey = "appointment:station_count:lock:" + storeId;
        Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 20, TimeUnit.SECONDS);
        if (Boolean.TRUE.equals(locked)) {
            try {
                // 双重检查（防止已被其他线程更新）
                stationCount = (Integer) redisTemplate.opsForValue().get(cacheKey);
                if (stationCount == null) {
                    newStationCountCache(storeId);
                    stationCount = (Integer) redisTemplate.opsForValue().get(cacheKey);
                }
            } finally {
                redisTemplate.delete(lockKey); // 释放锁
            }
        } else {
            // 其他线程等待后重试（最多等3次）
            for (int i = 0; i < 3; i++) {
                try {
                    Thread.sleep(100);
                    stationCount = (Integer) redisTemplate.opsForValue().get(cacheKey);
                    if (stationCount != null) {
                        break;
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
        return stationCount == null ? 0 : stationCount;
    }


    private void newStationCountCache(Integer storeId) {
        Result<Integer> result = storeApi.getStationCountByStoreId(storeId);
        if (result == null || result.getCode()!=ResultCode.SUCCESS.getCode()) {
            log.error("获取门店库存失败（远程服务调用失败）, storeId={}", storeId); // 修正日志
            throw new BusinessException(ResultCode.REMOTE_SERVICE_ERROR);
        }
        Integer stationCount = result.getData();
        if (stationCount == null) {
            log.warn("更新门店库存，门店库存为null, storeId={}", storeId);
            stationCount = 0; // 兜底处理，避免缓存null
        }
        redisTemplate.opsForValue().set("appointment:station_count:" + storeId,stationCount,1, TimeUnit.DAYS );
    }

    @Transactional(rollbackFor = Exception.class)
    public Result<Integer> createAppointment(NewAppointmentDto dto, Integer stationCount) {

        // 4. 创建预约主记录
        AppointmentMaster master = new AppointmentMaster();
        BeanUtils.copyProperties(dto, master);
        master.setCreateTime(LocalDateTime.now());
        master.setUpdateTime(LocalDateTime.now());
        appointmentMasterService.save(master);

        // 同步执行
        BigDecimal productTotalAmount = CollectionUtils.isEmpty(dto.getAppointmentProducts()) ?
                BigDecimal.ZERO : detailProductPackage(master.getId(), dto.getAppointmentProducts());
        BigDecimal serviceTotalAmount = CollectionUtils.isEmpty(dto.getAppointmentServices()) ?
                BigDecimal.ZERO : detailServicePackage(master.getId(), dto.getAppointmentServices());
        //更新字段
        master.setTotalAmount(productTotalAmount.add(serviceTotalAmount));
        appointmentMasterService.saveOrUpdate(master);

        // 7. 创建预约流程记录
        AppointmentProcess process = new AppointmentProcess();
        process.setAppointmentId(master.getId());
        process.setUserId(dto.getUserId());
        process.setAppointmentStatus(AppointmentConstant.ALREADY_CREATED);
        process.setOperationTime(LocalDateTime.now());
        appointmentProcessService.save(process);


        return Result.ok(master.getId());
    }

    private BigDecimal detailServicePackage(Integer appointmentId, List<AppointmentService> appointmentServices) {
        List<Integer> serviceIds = new ArrayList<>();
        List<AppointmentDetail> serviceDetails = new ArrayList<>();

        for (AppointmentService appointmentService : appointmentServices) {
            AppointmentDetail appointmentDetail = new AppointmentDetail();
            appointmentDetail.setAppointmentId(appointmentId);
            appointmentDetail.setQuantity(appointmentService.getQuantity());
            appointmentDetail.setItemId(appointmentService.getServiceId());
            appointmentDetail.setItemType("服务");
            appointmentDetailService.save(appointmentDetail); // 首次保存获取ID
            serviceDetails.add(appointmentDetail);
            serviceIds.add(appointmentService.getServiceId());
        }

        // 查询商品价格并构建映射
        List<Services> servicesList = servicesService.listByIds(serviceIds);
        Map<Integer, BigDecimal> serviceMap = servicesList.stream()
                .collect(Collectors.toMap(Services::getId,Services::getRetailPrice));

        BigDecimal serviceTotalAmount = BigDecimal.ZERO;
        // 计算总价并更新详情对象
        for (AppointmentDetail serviceDetail : serviceDetails) {
            // 安全获取价格，避免NullPointerException
            BigDecimal retailPrice = serviceMap.getOrDefault(serviceDetail.getItemId(), BigDecimal.ZERO);
            serviceDetail.setTotalPrice(calculateProductTotalPrice(retailPrice, serviceDetail.getQuantity()));
            serviceTotalAmount = serviceTotalAmount.add(serviceDetail.getTotalPrice());
        }

        // 批量更新总价（替代单个saveOrUpdate）
        appointmentDetailService.updateBatchById(serviceDetails);
        return serviceTotalAmount;

    }

    private BigDecimal detailProductPackage(Integer appointmentId, List<AppointmentProduct> appointmentProducts) {
        // 收集商品ID并创建详情对象
        List<Integer> productIds = new ArrayList<>();
        List<AppointmentDetail> productDetails = new ArrayList<>();

        for (AppointmentProduct appointmentProduct : appointmentProducts) {
            AppointmentDetail appointmentDetail = new AppointmentDetail();
            appointmentDetail.setAppointmentId(appointmentId);
            appointmentDetail.setQuantity(appointmentProduct.getQuantity());
            appointmentDetail.setItemId(appointmentProduct.getProductId());
            appointmentDetail.setItemType("产品");
            appointmentDetailService.save(appointmentDetail); // 首次保存获取ID
            productDetails.add(appointmentDetail);
            productIds.add(appointmentProduct.getProductId());
        }

        // 查询商品价格并构建映射
        List<Products> productsList = productsService.listByIds(productIds);
        Map<Integer, BigDecimal> productMap = productsList.stream()
                .collect(Collectors.toMap(Products::getId, Products::getRetailPrice));

        BigDecimal productTotalAmount = BigDecimal.ZERO;
        // 计算总价并更新详情对象
        for (AppointmentDetail productDetail : productDetails) {
            // 安全获取价格，避免NullPointerException
            BigDecimal retailPrice = productMap.getOrDefault(productDetail.getItemId(), BigDecimal.ZERO);
            productDetail.setTotalPrice(calculateProductTotalPrice(retailPrice, productDetail.getQuantity()));
            productTotalAmount = productTotalAmount.add(productDetail.getTotalPrice());
        }

        // 批量更新总价（替代单个saveOrUpdate）
        appointmentDetailService.updateBatchById(productDetails);
        return productTotalAmount;
    }

    // 提取计算总价的公共方法，减少重复代码-产品
    private BigDecimal calculateProductTotalPrice(BigDecimal retailPrice, int quantity) {
        if (quantity >= 2) {
            return retailPrice
                    .multiply(BigDecimal.valueOf(0.8))  // 8折
                    .multiply(BigDecimal.valueOf(quantity))
                    .setScale(2, RoundingMode.HALF_UP);  // 保留两位小数，四舍五入
        }
        return retailPrice
                .multiply(BigDecimal.valueOf(quantity))
                .setScale(2, RoundingMode.HALF_UP);
    }

}

//    public Integer getStationCount(Integer storeId) {
//        ValueOperations ops = redisTemplate.opsForValue();
//        String cacheKey = "appointment:station_count:" + storeId; // 规范键名
//        Integer stationCount = (Integer) ops.get(cacheKey);
//
//        if (stationCount == null) {
//            // 调用缓存更新方法
//            newStationCountCache(storeId);
//            // 重新从缓存获取（防止缓存更新成功但未获取）
//            stationCount = (Integer) ops.get(cacheKey);
//            // 兜底：若仍为null，默认0（避免返回null）
//            if (stationCount == null) {
//                stationCount = 0;
//            }
//        }
//        return stationCount;
//    }
